package ai.esc.speedy.admin.user.api

import ai.esc.speedy.common.util.id.IDGenerator
import ai.esc.speedy.common.valueobject.Extend
import cn.hutool.core.util.RandomUtil
import com.alibaba.fastjson.JSONObject
import com.fasterxml.jackson.annotation.JsonIgnore
import org.axonframework.modelling.command.TargetAggregateIdentifier
import java.util.*
import javax.persistence.*
import javax.validation.constraints.NotNull

// 注册用户
data class CreateAppUserCommand(@TargetAggregateIdentifier
                                val userId: String,
                                val appId: String,
                                val data: JSONObject,
                                val encryptionPassword: String?,
                                val phone: String)

// 更新用户资料
data class UpdateAppUserDataCommand(@TargetAggregateIdentifier
                                    val userId: String,
                                    val data: JSONObject)

// 更改用户状态
data class UpdateAppUserStatusCommand(@TargetAggregateIdentifier
                                      val userId: String,
                                      val status: Int)

// 修改密码
data class UpdateAppUserPasswordCommand(@TargetAggregateIdentifier
                                        val userId: String,
                                        val encryptionPassword: String)

// 找回密码，邮件
data class RetrieveAppUserPasswordByEmailCommand(@TargetAggregateIdentifier
                                                 val email: String,
                                                 val code: String)

// 找回密码，手机
data class RetrieveAppUserPasswordByPhoneCommand(@TargetAggregateIdentifier
                                                 val phone: String,
                                                 val code: String)

// 用户授权
data class UpdateAppUserPermissionsCommand(@TargetAggregateIdentifier
                                           val userId: String,
                                           val permissions: Set<String>,
                                           val resources: Set<String>)

// 修改手机号码
data class UpdateAppUserPhoneCommand(@TargetAggregateIdentifier
                                     val userId: String,
                                     val phone: String)

// 创建权限
data class CreatePermissionCommand(@TargetAggregateIdentifier
                                   val id: String,
                                   val name: String,
                                   val description: String,
                                   val data: Extend)

// 更新权限
data class UpdatePermissionCommand(@TargetAggregateIdentifier
                                   val id: String,
                                   val name: String,
                                   val description: String,
                                   val data: Extend,
                                   val resources: Set<String>)

// 删除权限
data class DeletePermissionCommand(@TargetAggregateIdentifier
                                   val identifier: String, val permissionIds: Set<String>)

// Event 无参构造函数用于序列化还原
data class CreateAppUserEvent(val appUser: AppUser?, val passport: Passport?) {
    constructor() : this(null, null)
}

data class UpdateAppUserEvent(val appUser: AppUser, val passport: Passport) {
    constructor() : this(AppUser(), Passport())
}

data class CreatePermissionEvent(val data: Permission?) {
    constructor() : this(null)
}

data class UpdatePermissionEvent(val data: Permission?) {
    constructor() : this(null)
}

data class DeletePermissionEvent(val ids: Set<String>?) {
    constructor() : this(null)
}

// Query
data class AppUserInfoQuery(val token: String)

data class AppUserListQuery(val offset: Int, val limit: Int)
data class AppUserTokenResponse(val accessToken: String, val refreshToken: String)
data class DynamicEncryptionCodeQuery(val identification: String)
data class LoginQuery(val appId: String, val username: String, val password: String)
data class SmsVerificationCodeQuery(val phone: String)
data class EmailVerificationCodeQuery(val email: String)
data class CheckAccountQuery(val account: String)
data class CheckVerificationCodeQuery(val phone: String, val code: String)
data class ThirdPartyLoginQuery(val type: String)


@Entity
@Table(name = "user_app_info")
data class App(
        @Id
        var fdId: String? = IDGenerator.generateID2Str(),
        var name: String? = null,
        // App版本
        var appVersion: String? = null,
        // 创建者
        var creator: String? = null,
        // 单点登录成功后重定向页面到应用的地址
        var ssoRedirectUri: String? = null,
        // 是否校验请求应用的域名是否合法
        var domain: String? = null,
        var status: Int? = 1,
        val createdAt: Date = Date(),
        /**
         * 数据推送地址。
         * 当用户系统发生某些事件时将数据推关给应用。
         * 比如：用户创建、修改，应用创建、修改等。
         */
        var dataUrl: String? = null,
        var options: String? = null,
        var updater: String? = null,
        var updatedAt: Date? = null
)

@Entity
@Table(name = "user_passport",
        uniqueConstraints = [UniqueConstraint(columnNames = arrayOf("account"))])
@NamedQueries(
        NamedQuery(name = "Passport.findByAccount",
                query = "SELECT p FROM Passport p WHERE p.account = :account")
)
data class Passport(
        @Id
        var fdId: String? = IDGenerator.generateID2Str(),
        var account: String? = null,
        var code: String? = null,
        var salt: String = RandomUtil.randomStringUpper(6),
        var saltPassword: String? = null,
        var status: Int = 1,
        @ElementCollection
        @JoinTable(name = "user_passport_permissions")
        var permissions: Set<String>? = null,
        @ElementCollection
        @JoinTable(name = "user_passport_resources")
        var resources: Set<String>? = null,
        // var phone: String? = null,
        val createdAt: Date = Date()
) {
    constructor(fdId: String) : this(fdId, null, null, RandomUtil.randomStringUpper(6), null, 1, null, null)
}

@Entity
@Table(name = "user_app_user")
@NamedQueries(
        NamedQuery(name = "AppUser.findByPassportId",
                query = "SELECT au FROM AppUser au WHERE au.passportId =:passportId"),
        NamedQuery(name = "AppUser.findByAccount",
                query = "SELECT au FROM AppUser au WHERE au.passportId =" +
                        "(SELECT p FROM Passport p WHERE p.account = :account)")
)
data class AppUser(
        @Id
        var userId: String? = IDGenerator.generateID2Str(),
        var appId: String? = null,
        var passportId: String? = null,
        var updatedAt: Date? = null,
        var status: Int = 1,
        @NotNull
        @Embedded
        var data: Extend? = null
) {
    constructor(userId: String) : this(userId, null, null, null, 1, null)
    constructor(userId: String, extend: Extend) : this(userId, null, null, null, 1, extend)

}

@Entity
@Table(name = "user_client")
data class Client(
        @Id
        var fdId: String? = IDGenerator.generateID2Str(),
        var clientName: String? = null,
        var clientId: String? = null,
        var clientSecret: String? = null
)

@Entity
@Table(name = "user_org")
data class Org(
        @Id
        var fdId: String? = IDGenerator.generateID2Str(),
        var name: String? = null,
        var code: String? = null,
        // 关联关系
        @Lob
        val contact: String? = null,
        @Embedded
        var data: Extend? = null,
        var creator: String? = null,
        // 直接父组织ID
        var parent: String? = null,
        // 完整父组织ID列表
        @ElementCollection
        @JoinTable(name = "user_org_parents")
        var parents: Set<String>? = null,
        var directParent: String? = null,
        var sort: Int = 99999,
        var status: Int = 1,
        var updater: String? = null,
        @ElementCollection
        @JoinTable(name = "user_org_app_ids")
        var appIds: Set<String>? = null,
        val createdAt: Date = Date(),
        var updatedAt: Date? = null
)

@Entity
@Table(name = "user_permission")
data class Permission(
        @Id
        var fdId: String? = IDGenerator.generateID2Str(),
        var name: String? = null,
        var description: String? = null,
        @Embedded
        var data: Extend? = null,
        @ElementCollection
        @JoinTable(name = "user_permission_resources")
        var resources: Set<String>? = null
)

@Entity
@Table(name = "user_resource")
data class Resource(
        @Id
        var fdId: String? = IDGenerator.generateID2Str(),
        var name: String? = null,
        var description: String? = null,
        @Embedded
        var data: Extend? = null
)
